package com.ykl.demo.ctrl;

import com.ykl.base.restful.BasicEntityServiceCtrl;
import com.ykl.base.restful.Res;
import com.ykl.demo.ctrl.vm.SpcRoomListForm;
import com.ykl.demo.entity.SpcRoom;
import com.ykl.demo.model.RoomImportResModel;
import com.ykl.demo.service.SpcRoomService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("/spcroom")
public class SpcRoomCtrl extends BasicEntityServiceCtrl<SpcRoom> {

    private SpcRoomService mmServ;

    public SpcRoomCtrl(SpcRoomService service) {
        super(service);
        this.mmServ = service;
    }

    /**
     * 增加/修改机房接口.
     * <p>
     * 接口协议	HTTP POST<br/>
     * 数据格式	Json<br/>
     * 接口描述	增加一条机房信息。需要参照字段表中“说明”，“字段类型”，“限定”相关要求，先进行数据验证，再执行插入。<br/>
     * </p>
     */
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    public ResponseEntity<Res<SpcRoom>> save(
            @RequestBody @Valid
                    SpcRoom room,
            BindingResult valRes
    ) {
        return validate(valRes, "增加/修改机房接口请求格式错误，详情：", () -> super.save(room));
    }


    /**
     * 查询机房接口.
     * <p>接口协议	HTTP POST<br/>
     * 数据格式	Json<br/>
     * 接口描述	根据入参查询符合条件的机房信息，信息中需要携带“所属局站名称”。<br/>
     * 查询条件应包含：<br/>
     * “机房ID”等于“入参机房ID”<br/>
     * “机房名称”等于“入参机房名称”<br/>
     * “机房名称”包含“入参机房名称”<br/>
     * “所属局站名称”以“入参所属局站名称”开始<br/>
     * </p>
     */
    @RequestMapping(value = "/list", method = RequestMethod.POST)
    public ResponseEntity<Res<Page<SpcRoom>>> list(
            @RequestBody @Valid
                    SpcRoomListForm form,
            BindingResult valRes
    ) {
        return validate(valRes, "查询机房接口请求格式错误，详情：", () -> mmServ.querySpcRoom(
                StringUtils.trimToEmpty(form.getRoomId()),
                StringUtils.trimToEmpty(form.getRoomName()),
                StringUtils.trimToEmpty(form.getRoomNameContains()),
                StringUtils.trimToEmpty(form.getRoomNameStartWith()),
                form.getPgIdxB0(), form.getPgSize(), Collections.emptyList()));
    }


    /**
     * 导出机房接口.
     * <p>接口协议	HTTP POST<br/>
     * 数据格式	File<br/>
     * 接口描述	根据本文最下方附件“机房导入导出模版”，完成数据库中所有机房CSV的导出。<br/>
     * </p>
     */
    @RequestMapping(value = "/exportAllAsCsv", method = {RequestMethod.POST,RequestMethod.GET})
    public void exportAllRooms(HttpServletRequest req, HttpServletResponse resp){

        writeDownloadFile(req, resp, DEFAULT_CHARSET,
                ()->"全部机房-"+new SimpleDateFormat("yyyy-MM-dd_hhmmss").format(new Date()) +".csv",
                ()->mmServ.exportAll(DEFAULT_CHARSET)
        );

    }

    /**
     * 导入机房接口
     * 接口协议	HTTP POST
     * 数据格式	File
     * 接口描述	根据本文最下方附件“机房导入导出模版”，完成机房CSV的导入。
     * 要求如下：
     * 1.	“机房导入导出模版”中信息，如果“机房ID”为空，则此条数据作“新增”处理；如果“机房ID”不为空，则此条数据作“更新”对应ID数据处理；
     * 2.	如果“机房导入导出模版”中信息，局站名称不存在于局站表中，则自动新增一条局站数据；
     * 3.	导入前，需要验证数据是否符合字段表中“说明”，“字段类型”，“限定”相关要求，如果不符合，应记录不符合的原因。
     * 并在所有的数据处理完成后，将所有的错误数据，以“机房导入导出模版”的形式提供返回，并新建一列记录“数据错误原因”；
     */
    @RequestMapping(value="/importRoomAsFormFromCsv", method = RequestMethod.POST)
    public void importRoomAsFormFromCsv(MultipartHttpServletRequest req, HttpServletResponse resp){
        Iterator<String> filenames = req.getFileNames();
        if(filenames==null){
            writeDownloadFile(req, resp, StandardCharsets.UTF_8,
                    ()->"empty_upload_form.result.txt",
                    ()->"没有在导入请求中找到文件，注意form方式上传，需要指定表单中file项的名字,且不能为空".getBytes(StandardCharsets.UTF_8)
            );
            return;
        }
        List<RoomImportResModel> ls = new ArrayList<>();


        while(filenames.hasNext()){
            String fieldName = filenames.next();
            try {
                MultipartFile file = req.getFile(fieldName);
                if(file==null){
                    writeDownloadFile(req, resp, StandardCharsets.UTF_8,
                            ()->"not_found_form_file.result.txt",
                            ()->String.format("没有找到请求中%s项对应的文件",fieldName).getBytes(StandardCharsets.UTF_8)
                    );
                    return;
                }
                byte[] bytes = file.getBytes();
                String name = file.getName();
                ls.addAll(mmServ.importFromCsv(name,bytes));
            }catch (Exception ex){
                log.error(ex.getLocalizedMessage(), ex);
                writeDownloadFile(req, resp, DEFAULT_CHARSET, ()->fieldName+".result.txt",
                        ()->"处理中发生未知异常".getBytes(DEFAULT_CHARSET));
                return;
            }
        }

        writeDownloadFile(req, resp, DEFAULT_CHARSET, ()-> String.format("机房导入结果_%s.result.txt",
                        new SimpleDateFormat("yyyy-MM-dd_hhmmss").format(new Date())),
                ()->mmServ.buildImportResultOutput(ls, DEFAULT_CHARSET));

    }

}
